#import "MapAppSettingsView.h"

// Singleton instance of MapAppSettingsView
static MapAppSettingsView* sharedSettingsView = nil;

/**
 * A MapAppSettingsView is an object representing the view that provides
 * the functionality to modify the application settings.
 *
 * @author      James Lin
 * @author      Justin Hollander
 * @version     2.2.5
 * @since       1.1.1
 * @see         BusDirectoryDelegate
 * @see         ValueSelectorDelegate
 * @see         UIAlertViewDelegate
 */
@implementation MapAppSettingsView

@synthesize mapTypeControl;
@synthesize eventIntervalLabel;

/**
 * Retrieve the shared instance of the application settings view.
 *
 * @return  the shared instance of MapAppSettingsView
 */
+ (MapAppSettingsView*)sharedSettingsView {
	@synchronized(self) {
		if (sharedSettingsView == nil) {
			sharedSettingsView = [[MapAppSettingsView alloc] init];
		}
		return sharedSettingsView;
	}
}

/**
 * Allocate the application settings view.
 *
 * @return  the newly allocated shared instance of MapAppSettingsView
 */
+ (id) alloc {
	@synchronized(self) {
		sharedSettingsView = [super alloc];
		return sharedSettingsView;
	}
}

/**
 * Retrieve a copy of the application settings view.
 *
 * @return  the shared instance of MapAppSettingsView
 */
+ (id) copy {
	@synchronized(self) {
		return sharedSettingsView;
	}
}

/**
 * Initialize the shared instance of the application settings view.
 *
 * @return  the initialized MapAppSettingsView
 */
- (id)init {
	if (self = [super init]) {
		self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 
																	   VIEW_WIDTH, 
																	   VIEW_HEIGHT) 
													  style:UITableViewStyleGrouped];
		self.navigationItem.title = @"Settings";
		settings = [MapAppSettings sharedSettings];
	}
	return self;
}

/**
 * Display the application settings view.
 *
 * Pushes this view onto the navigation controller stack of the parent
 * view. Upon tapping the back button, the view is automatically 
 * popped off the top of the navigation stack.
 *
 * @param navController  the navigation controller of the parent view
 */
- (void)displayWithNavController:(UINavigationController*)navController {
	parentNav = navController;
	[navController pushViewController:self animated:YES];
}

/**
 * Reload pin note count label when view appears.
 */
- (void)viewWillAppear:(BOOL)animated {
	NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:PinNotesGroup];
	NSArray* pathArray = [NSArray arrayWithObject:indexPath];
	
	[self.tableView reloadRowsAtIndexPaths:pathArray 
						  withRowAnimation:UITableViewRowAnimationNone];
	[super viewWillAppear:animated];
}

/**
 * Set the main view controller reference.
 *
 * @param viewController  the main view controller
 */
- (void)setMVC:(MapViewController*)viewController {
	mvc = viewController;
}

/**
 * Handle a notification that a value has been selected.
 *
 * @param value       the value that was selected
 * @param identifier  the identifier for the source from which the value was selected
 * @see               ValueSelectorDelegate
 */
- (void)valueSelected:(id)value selectorIdentifier:(NSUInteger)identifier {
	switch (identifier) {
		case MapTypeSelector:
			settings.currentMapType = [(NSNumber*)value intValue];
			mvc.mapView.mapType = settings.currentMapType;
			break;
		case CampusSelector:
			settings.campus = [(NSNumber*)value intValue];
			[mvc setDefaultMapRegion];
			break;
		case EventIntervalSelector:
			settings.eventCacheInterval = [(NSNumber*)value doubleValue];
			[mvc runEventCaching];
			break;
		case FoursquareVenueLimitSelector:
			settings.foursquareVenueLimit = [(NSNumber*)value intValue];
			break;
		case FoursquareTipLimitSelector:
			settings.foursquareTipLimit = [(NSNumber*)value intValue];
			break;
	}
	
	[settings saveSettings];
	[self.tableView reloadData];
}

/**
 * Notify of the latest directory update with a date timestamp.
 *
 * @param date  the date timestamp of the latest update
 */
- (void)updateDirTimestamp:(NSDate*)date {
	if (settings.dirUpdateTimestamp) {
		[settings.dirUpdateTimestamp release];
	}
	
	settings.dirUpdateTimestamp = date;
	[settings saveSettings];
	[self.tableView reloadData];
}

/**
 * Get the number of sections in the table.
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
    return 6;
}

/**
 * Get the number of rows in each section of the table.
 */
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
	switch (section) {
		case MapGroup:
			return 2;
			break;
		case PinNotesGroup:
			return 2;
			break;
		case FoursquareGroup:
			return 2;
			break;
		case DirectoryGroup:
			return 2;
			break;
		case EventGroup:
			return 2;
			break;
		case MiscGroup:
			return 1;
			break;
	}
	return 0;
}

/**
 * Get the title of each section of the table.
 */
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section {
	switch (section) {
		case MapGroup:
			return @"Map Settings";
			break;
		case PinNotesGroup:
			return @"Pin Notes Information";
			break;
		case FoursquareGroup:
			return @"Foursquare Settings";
			break;
		case DirectoryGroup:
			return @"Directory Information";
			break;
		case EventGroup:
			return @"Event Settings";
			break;
		case MiscGroup:
			return @"";
			break;
	}
	return @"";
}

/**
 * Get the height of each row of the table.
 */
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
	if ([indexPath section] == EventGroup && [indexPath row] == 0) {
		return 90;
	} else {
		return DEFAULT_CELL_HEIGHT;
	}
}

/**
 * Update the cell content.
 */
- (UITableViewCell*)tableView:(UITableView*)tableView 
		cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    static NSString* DefaultCellIdentifier = @"SettingsStyleDefaultCellIdentifier";
	static NSString* ValueCellIdentifier = @"SettingsStyleValueCellIdentifier";
	static NSString* SubtitleCellIdentifier = @"SettingsStyleSubtitleCellIdentifier";
	UITableViewCell* cell;
	
	// Grab the cell content relevant to the section and row
    switch ([indexPath section]) {
        case MapGroup:
        {
            if ([indexPath row] == 0) {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Map Type:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				cell.detailTextLabel.text = [[SFUConstants getMapTypes] 
											 objectForKey:[NSNumber numberWithInt:(int)settings.currentMapType]];
				cell.detailTextLabel.font = [UIFont systemFontOfSize:15.0];
				cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            } else {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				
				cell.textLabel.text = @"Default Campus:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				cell.detailTextLabel.text = [[SFUConstants getCampuses] 
											 objectForKey:[NSNumber numberWithInt:(int)settings.campus]];
				cell.detailTextLabel.font = [UIFont systemFontOfSize:15.0];
				cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
				
            }
            break;
        }
		case PinNotesGroup:
        {
			if ([indexPath row] == 0) {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Number of Pin Notes:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				int size = [[AddressAnnotationCollection sharedAddressAnnotationCollection] size];
				cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", size];
				cell.detailTextLabel.font = [UIFont systemFontOfSize:17.0];
				cell.selectionStyle = UITableViewCellSelectionStyleNone;
				cell.accessoryType = UITableViewCellAccessoryNone;
            } else {
				cell = [tableView dequeueReusableCellWithIdentifier:DefaultCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
												   reuseIdentifier:DefaultCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Delete All Pin Notes";
				cell.textLabel.textAlignment = UITextAlignmentCenter;
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				cell.accessoryType = UITableViewCellAccessoryNone;
			}
            break; 
        }
		case FoursquareGroup:
        {
			if ([indexPath row] == 0) {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Number of Venues to Display:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				int num = [[MapAppSettings sharedSettings] foursquareVenueLimit];
				cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", num];
				cell.detailTextLabel.font = [UIFont systemFontOfSize:17.0];
				cell.selectionStyle = UITableViewCellAccessoryDisclosureIndicator;
				cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
			} else {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Number of Tips to Display:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				int num = [[MapAppSettings sharedSettings] foursquareTipLimit];
				cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", num];
				cell.detailTextLabel.font = [UIFont systemFontOfSize:17.0];
				cell.selectionStyle = UITableViewCellAccessoryDisclosureIndicator;
				cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
			}
            break; 
        }
		case DirectoryGroup:
        {
            if ([indexPath row] == 0) {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
				[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
				[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
				
				cell.textLabel.text = @"Last Updated on:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				
				if (settings.dirUpdateTimestamp == nil) {
					cell.detailTextLabel.text = @"Never";
				} else {
					cell.detailTextLabel.text = [dateFormatter stringFromDate:settings.dirUpdateTimestamp];
				}
				
				cell.detailTextLabel.font = [UIFont systemFontOfSize:15.0];
				cell.selectionStyle = UITableViewCellSelectionStyleNone;
            } else {
				cell = [tableView dequeueReusableCellWithIdentifier:DefaultCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
												   reuseIdentifier:DefaultCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Update the Directory";
				cell.textLabel.textAlignment = UITextAlignmentCenter;
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				cell.detailTextLabel.text = nil;
				cell.accessoryType = UITableViewCellAccessoryNone;
			}
            break; 
        }
		case EventGroup:
        {
            if ([indexPath row] == 0) {
				cell = [tableView dequeueReusableCellWithIdentifier:SubtitleCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle 
												   reuseIdentifier:SubtitleCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"";
				cell.textLabel.font = [UIFont systemFontOfSize:12.5];
				cell.detailTextLabel.text = @"The update interval is the frequency at which the event information is updated. Shorter intervals will consume more bandwidth and battery power. Change only if necessary.";
				cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
				cell.detailTextLabel.numberOfLines = 0;
				cell.detailTextLabel.font = [UIFont systemFontOfSize:12.5];
				cell.selectionStyle = UITableViewCellSelectionStyleNone;
			} else {
				cell = [tableView dequeueReusableCellWithIdentifier:ValueCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 
												   reuseIdentifier:ValueCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Update Interval:";
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				cell.detailTextLabel.text = [[SFUConstants getCacheIntervals] 
											 objectForKey:[NSNumber numberWithInt:(int)settings.eventCacheInterval]];
				cell.detailTextLabel.font = [UIFont systemFontOfSize:15.0];
				cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
				cell.selectionStyle = UITableViewCellAccessoryDisclosureIndicator;
            }
            break; 
        }
		case MiscGroup:
        {
            if ([indexPath row] == 0) {
				cell = [tableView dequeueReusableCellWithIdentifier:DefaultCellIdentifier];
				
				if (cell == nil) {
					cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
												   reuseIdentifier:DefaultCellIdentifier] autorelease];
				}
				
				cell.textLabel.text = @"Reset Settings to Default";
				cell.textLabel.textAlignment = UITextAlignmentCenter;
				cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
				cell.accessoryType = UITableViewCellAccessoryNone;
			}
            break; 
        }
    }
	
    return cell;
}

/**
 * Handle the selection of a row of the table.
 */
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
	[tableView deselectRowAtIndexPath:indexPath animated:YES];
	
	switch ([indexPath section]) {
        case MapGroup:
        {
            if ([indexPath row] == 0) {
                ValueSelectorView* vsv = [[ValueSelectorView alloc] initWithIdentifier:MapTypeSelector 
																				values:[SFUConstants getMapTypes]];
				[vsv setDelegate:self];
				[vsv displayViewWithTitle:@"Map Type" 
							navController:self.navigationController 
							selectedValue:[NSNumber numberWithInt:(int)settings.currentMapType]];
				[vsv autorelease];
            } else {
				ValueSelectorView* vsv = [[ValueSelectorView alloc] initWithIdentifier:CampusSelector 
																				values:[SFUConstants getCampuses]];
				[vsv setDelegate:self];
				[vsv displayViewWithTitle:@"Default Campus" 
							navController:self.navigationController 
							selectedValue:[NSNumber numberWithInt:(int)settings.campus]];
				[vsv autorelease];
				
				
            }
            break;
        }
		case PinNotesGroup:
		{
			if ([indexPath row] == 0) {
                // Number of pin notes cell: do nothing
            } else {
				NSString* msg = @"Are you sure you want to delete all pin notes?";
				[GraphicsUtilities displayConfirmationWithTitle:@"" 
														message:msg 
															tag:DeletePinNotesTag 
													   delegate:self];
            }
            break;
		}
		case FoursquareGroup:
		{
			if ([indexPath row] == 0) {
                ValueSelectorView* vsv = [[ValueSelectorView alloc] initWithIdentifier:FoursquareVenueLimitSelector 
																				values:[SFUConstants getVenueLimits]];
				[vsv setDelegate:self];
				[vsv displayViewWithTitle:@"Venues to Display" 
							navController:self.navigationController 
							selectedValue:[NSNumber numberWithInt:(int)settings.foursquareVenueLimit]];
				[vsv autorelease];
            } else {
                ValueSelectorView* vsv = [[ValueSelectorView alloc] initWithIdentifier:FoursquareTipLimitSelector 
																				values:[SFUConstants getTipLimits]];
				[vsv setDelegate:self];
				[vsv displayViewWithTitle:@"Tips to Display" 
							navController:self.navigationController 
							selectedValue:[NSNumber numberWithInt:(int)settings.foursquareTipLimit]];
				[vsv autorelease];
            }
            break;
		}
		case DirectoryGroup:
		{
			if ([indexPath row] == 0) {
                // Last directory update cell: do nothing
            } else {
				NSString* title = @"Updating may take 1-2 minutes.";
				NSString* msg = @"Would you like to continue?";
				[GraphicsUtilities displayConfirmationWithTitle:title 
														message:msg 
															tag:UpdateDirectoryTag 
													   delegate:self];
            }
            break;
		}
		case EventGroup:
		{
			if ([indexPath row] == 0) {
				// Event caching interval description cell: do nothing
			} else {
				ValueSelectorView* vsv = [[ValueSelectorView alloc] initWithIdentifier:EventIntervalSelector 
																				values:[SFUConstants getCacheIntervals]];
				[vsv setDelegate:self];
				[vsv displayViewWithTitle:@"Update Interval" 
							navController:self.navigationController 
							selectedValue:[NSNumber numberWithInt:(int)settings.eventCacheInterval]];
				[vsv autorelease];
			}
			break;
		}
		case MiscGroup:
		{
			if ([indexPath row] == 0) {
				NSString* msg = @"Are you sure you want to reset all settings to default?";
				[GraphicsUtilities displayConfirmationWithTitle:@"" 
														message:msg 
															tag:ResetSettingsTag 
													   delegate:self];
            }
            break;
		}
    }
}

/**
 * Handle the confirmation of the alert view.
 *
 * @see  UIAlertViewDelegate
 */
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	switch (alertView.tag) {
		case DeletePinNotesTag:
			if (buttonIndex == 0) {
				[mvc resetPinNotes];
				[self.tableView reloadData];
			}
			break;
		case UpdateDirectoryTag:
			if (buttonIndex == 0) {
				[[BusDirectoryManager sharedBusDirectoryManager] updateDirectory];
			}
			break;
		case ResetSettingsTag:
			if (buttonIndex == 0) {
				[settings setDefault];
				[self.tableView reloadData];
				mvc.mapView.mapType = settings.currentMapType;
				[mvc setDefaultMapRegion];
				[mvc runEventCaching];
			}
			break;
	}
}

/**
 * Deallocate the application settings view.
 */
- (void)dealloc {
	[mapTypeControl release];
	mapTypeControl = nil;
	[eventIntervalLabel release];
	eventIntervalLabel = nil;
	settings = nil;
	parentNav = nil;
    [super dealloc];
}

@end